#!/usr/bin/env python
# -*- coding: utf-8 -*-

import md5
import os, os.path, sys
import tempfile

import unittest

from potherb import log
from potherb.cellstore import CellStore,CellStoreScanner
from potherb.scan import ScanContext,ScanSpec

class   TestCellStoreScan_001(unittest.TestCase) :

    def setUp(self) :
        store_fd, store_name = tempfile.mkstemp(suffix='.store', prefix='cell_')
        os.close(store_fd)
        self.store_name = store_name

        records_per_cell = 8
        self.lookup_table = {}      # a set of testing data

        haystack = []
        for k in range(1, records_per_cell + 1) :
            data = '%016d' % k
            key = md5.new(data).hexdigest()
            haystack.append((key, data))
            self.lookup_table[key] = data
        haystack.sort(reverse=True)

        store = CellStore(self.store_name)
        for _k,_v in haystack :
            store.append(_k,_v)
        del store

        self.store = CellStore(self.store_name)
        self.scanner = None
        # setUp()

    def tearDown(self) :
        if self.scanner :
            del self.scanner
            self.scanner = None
        if self.store :
            del self.store
            self.store = None
        if os.path.exists(self.store_name) :
            os.remove(self.store_name)
        # tearDown()

    def test_scanAll(self) :
        scan_context = ScanContext()
        scan_spec = ScanSpec()
        #scan_spec.setRowInterval('',r'\xFF\xFF\xFF\xFF')
        scan_context.scan_spec = scan_spec
        self.scanner = CellStoreScanner(scan_context)
        self.scanner.attach(self.store)

        try :
            try :
                for key,data in self.scanner :
                    if key in self.lookup_table :
                        data_expect = self.lookup_table[ key ]
                        del self.lookup_table[ key ]
                        self.assertEqual(data, data_expect, 'key="%s"' % key)
                    else :
                        self.fail('Invalid key "%s"' % key)
            except StopIteration :
                pass
            except :
                nil, t, v, tbinfo = log.compact_traceback()
                log.error('Uncaught Exception -- %s:%s %s', t, v, tbinfo)
                self.fail('Uncaught Exception -- %s:%s %s' % (t, v, tbinfo))
        finally :
            # if there are some key missed
            if self.lookup_table :
                self.fail('scan missed some key: %s' % self.lookup_table)

        self.scanner.detach()
        # test_scanAll()

    def test_scanOne(self) :
        scan_context = ScanContext()

        scan_spec = ScanSpec()

        for key,data in self.lookup_table.iteritems() :
            hited = False
            try :
                scan_spec.setRow(key)
                scan_context.scan_spec = scan_spec
                self.scanner = CellStoreScanner(scan_context)
                self.scanner.attach(self.store)

                _key,_data = self.scanner.next()
                self.assertEqual(key, _key, 'Bad Key')
                self.assertEqual(data, _data, 'Bad Data')
                hited = True

                _key,_data = self.scanner.next()
                self.fail('Scanner return more data (key:"%s" value:"%s"' % (_key, _data))
            except StopIteration :
                if not hited :
                    self.fail('MISS key:"%s" data:"%s"' % (key,data))

                self.scanner.detach()
            except :
                nil, t, v, tbinfo = log.compact_traceback()
                self.fail('Uncaught Exception -- %s:%s %s' % (t, v, tbinfo))

            del self.scanner
            self.scanner = None
        # test_hitOneRow()

    # class TestCellStoreScan_001

#######################################################################

if  __name__ == '__main__' :
    log.enableDebug()

    unittest.main()
